home *** CD-ROM | disk | FTP | other *** search
Wrap
/* ** termMain.c ** ** Program main routines and event loop ** ** Copyright © 1990-1994 by Olaf `Olsen' Barthel ** All Rights Reserved */ #include "termGlobal.h" #include "termEmulationProcess.h" /* Argument vectors offsets. */ enum { ARG_WINDOW,ARG_PUBSCREEN,ARG_STARTUP,ARG_PORTNAME,ARG_SETTINGS,ARG_UNIT,ARG_DEVICE, ARG_NEW,ARG_SYNC,ARG_QUIET,ARG_BEHIND,ARG_DEBUG, ARG_COUNT }; /* Argument template. */ #define ARGTEMPLATE "WINDOW/K,PUBSCREEN/K,STARTUP/K,PORTNAME/K,SETTINGS/K,UNIT/K/N,DEVICE/K,NEW/S,SYNC/S,QUIET/S,BEHIND/S,DEBUG/S" /* Local config path variable. */ STATIC STRPTR ConfigPath; STATIC UBYTE __far ThePath[MAX_FILENAME_LENGTH]; /* Local dialing list. */ STATIC struct List *LocalDialList; STATIC LONG LocalCount = -1; /* Startup file name. */ STATIC UBYTE __far StartupFile[MAX_FILENAME_LENGTH]; /* Segment split routine, has to be local. */ STATIC struct Process * __regargs SegmentSplit(STRPTR Name,BYTE Pri,LONG StackSize,APTR Function); STATIC VOID CloseLibs(VOID); /* main(): * * This is our main entry point, check for the right * Kickstart version and fire off the background task * if approritate. */ LONG main() { STRPTR Result; /* Are we running as a child of Workbench? */ ThisProcess = (struct Process *)SysBase -> ThisTask; if(!ThisProcess -> pr_CLI) { WaitPort(&ThisProcess -> pr_MsgPort); WBenchMsg = (struct WBStartup *)GetMsg(&ThisProcess -> pr_MsgPort); } else WBenchMsg = NULL; /* Now try to open dos.library and utility.library and go on examining * our calling parameters. */ if(!(DOSBase = (struct DosLibrary *)OpenLibrary("dos.library",0))) { CloseLibs(); return(RETURN_FAIL); } if(!(UtilityBase = OpenLibrary("utility.library",0))) { CloseLibs(); return(RETURN_FAIL); } /* We were called from Shell. */ if(ThisProcess -> pr_CLI) { STRPTR *ArgArray; /* Use the cute ReadArgs parser, allocate the * argument vectors... */ if(ArgArray = (STRPTR *)AllocVec(sizeof(STRPTR) * (ARG_COUNT),MEMF_ANY|MEMF_CLEAR)) { struct RDArgs *ArgsPtr; if(ArgsPtr = (struct RDArgs *)AllocDosObject(DOS_RDARGS,TAG_DONE)) { ArgsPtr -> RDA_ExtHelp = "\nUsage: term [WINDOW <Name>] [PUBSCREEN <Name>] [STARTUP <File name>]\n" " [SETTINGS <File or path name>] [UNIT <Number>] [DEVICE <Name>]\n" " [NEW] [SYNC] [QUIET] [BEHIND]\n\n" " Window = Output window specifier\n" " PubScreen = Name of public screen to open window upon\n" " Startup = ARexx script file to run on startup\n" " Settings = Main configuration file name or path name to search for it\n" " Unit = Serial device driver unit number\n" " Device = Serial device driver name\n" " New = Spawn a new `term' process\n" " Sync = Keep links to Shell environment\n" " Quiet = Start iconified\n" " Behind = Open screen behind all other screens, don't activate the window\n\n"; /* Parse the args (if any). */ if(ReadArgs(ARGTEMPLATE,(LONG *)ArgArray,ArgsPtr)) { /* Pop a running `term' to the front? */ if((TermPort = (struct TermPort *)FindPort("term Port")) && !ArgArray[ARG_NEW]) { if(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",0)) { if(TermPort -> TopWindow) BumpWindow(TermPort -> TopWindow); } TermPort = NULL; FreeArgs(ArgsPtr); FreeDosObject(DOS_RDARGS,ArgsPtr); FreeVec(ArgArray); CloseLibs(); return(RETURN_OK); } if(ArgArray[ARG_DEBUG]) DebugFlag = TRUE; /* Are we to use a special settings path? */ if(ArgArray[ARG_SETTINGS]) { ConfigPath = ThePath; strcpy(ThePath,ArgArray[ARG_SETTINGS]); } /* Are we to use a special ARexx host port name? */ if(ArgArray[ARG_PORTNAME]) strcpy(RexxPortName,ArgArray[ARG_PORTNAME]); /* Are we to use a special output window name? */ if(ArgArray[ARG_WINDOW]) strcpy(WindowName,ArgArray[ARG_WINDOW]); /* Are we to run an ARexx script on startup? */ if(ArgArray[ARG_STARTUP]) strcpy(StartupFile,ArgArray[ARG_STARTUP]); /* Are we to open a window on a public screen? */ if(ArgArray[ARG_PUBSCREEN]) strcpy(SomePubScreenName,ArgArray[ARG_PUBSCREEN]); /* Are we to use a special device? */ if(ArgArray[ARG_DEVICE]) { strcpy(NewDevice,ArgArray[ARG_DEVICE]); UseNewDevice = TRUE; } /* Are we to use a special unit number? */ if(ArgArray[ARG_UNIT]) { NewUnit = *(LONG *)ArgArray[ARG_UNIT]; UseNewUnit = TRUE; } /* Are we to start up iconified? */ if(ArgArray[ARG_QUIET]) { if(!StartupFile[0]) DoIconify = TRUE; } /* Hide the screen and don't activate the window? */ if(ArgArray[ARG_BEHIND]) KeepQuiet = TRUE; /* We are to keep our links to * the Shell. */ if(ArgArray[ARG_SYNC] || !ThisProcess -> pr_HomeDir) { BYTE OldPri = ThisProcess -> pr_Task . tc_Node . ln_Pri; /* Do we have enough stack space available? */ if(((struct CommandLineInterface *)BADDR(ThisProcess -> pr_CLI)) -> cli_DefaultStack < 4096) { Printf("\33[1mterm:\33[0m %s.\a\n","Sorry, the Shell stack must be at least 16384 bytes large"); FreeArgs(ArgsPtr); FreeDosObject(DOS_RDARGS,ArgsPtr); FreeVec(ArgArray); CloseLibs(); return(RETURN_FAIL); } /* Open our resources and * squeak on failure. */ if(Result = OpenAll(ConfigPath)) { if(Result[0]) Printf("\33[1mterm:\33[0m %s!\a\n",Result); FreeArgs(ArgsPtr); FreeDosObject(DOS_RDARGS,ArgsPtr); FreeVec(ArgArray); CloseAll(TRUE); return(RETURN_FAIL); } /* Go into main input * loop. */ HandleInput(); /* Free the argument * data. */ FreeArgs(ArgsPtr); FreeDosObject(DOS_RDARGS,ArgsPtr); FreeVec(ArgArray); /* Restore old priority. */ SetTaskPri(ThisProcess,(LONG)OldPri); /* Terminate execution. */ CloseAll(TRUE); return(RETURN_OK); } FreeArgs(ArgsPtr); } else { PrintFault(IoErr(),"term"); FreeDosObject(DOS_RDARGS,ArgsPtr); FreeVec(ArgArray); CloseLibs(); return(RETURN_ERROR); } FreeDosObject(DOS_RDARGS,ArgsPtr); } FreeVec(ArgArray); /* Create a new process from our code. */ if(!SegmentSplit("term main process",0,16384,HandleInput)) { Printf("\33[1mterm:\33[0m Failed to create new process!\a\n"); CloseLibs(); return(RETURN_FAIL); } } else { Printf("\33[1mterm:\33[0m Failed to allocate argument vectors!\a\n"); CloseLibs(); return(RETURN_FAIL); } } else { LONG StackSize; StackSize = (LONG)SysBase -> ThisTask -> tc_SPUpper - (LONG)SysBase -> ThisTask -> tc_SPLower; if(StackSize < 16384) { if(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",37)) MyEasyRequest(NULL,"`term' has a problem:\nThe current stack size of %ld bytes is too low,\nplease edit the tool icon to use at least\n16384 bytes and restart the program.","Continue",StackSize); CloseLibs(); return(RETURN_FAIL); } else { WBenchLock = CurrentDir(WBenchMsg -> sm_ArgList -> wa_Lock); /* Open icon.library, we want to take a * look at the icon. */ if(IconBase = OpenLibrary("icon.library",0)) { struct DiskObject *Icon; /* Try to read the icon file. */ if(Icon = GetProgramIcon()) { STRPTR Type; if(FindToolType(Icon -> do_ToolTypes,"DEBUG")) DebugFlag = TRUE; /* Look for a `Settings' tooltype. */ if(ConfigPath = FindToolType(Icon -> do_ToolTypes,"SETTINGS")) { /* Remember the path and continue. */ strcpy(ThePath,ConfigPath); ConfigPath = ThePath; } /* Look for a `Portname' tooltype. */ if(Type = FindToolType(Icon -> do_ToolTypes,"PORTNAME")) strcpy(RexxPortName,Type); else RexxPortName[0] = 0; /* Look for a `Window' tooltype. */ if(Type = FindToolType(Icon -> do_ToolTypes,"WINDOW")) strcpy(WindowName,Type); else WindowName[0] = 0; /* Look for a `Pubscreen' tooltype. */ if(Type = FindToolType(Icon -> do_ToolTypes,"PUBSCREEN")) strcpy(SomePubScreenName,Type); else SomePubScreenName[0] = 0; /* Look for a `Startup' tooltype. */ if(Type = FindToolType(Icon -> do_ToolTypes,"STARTUP")) strcpy(StartupFile,Type); else StartupFile[0] = 0; /* Look for a `Device' tooltype. */ if(Type = FindToolType(Icon -> do_ToolTypes,"DEVICE")) { if(Type[0]) { strcpy(NewDevice,Type); UseNewDevice = TRUE; } } /* Look for a `Unit' tooltype. */ if(Type = FindToolType(Icon -> do_ToolTypes,"UNIT")) { if(Type[0]) { NewUnit = Atol(Type); UseNewUnit = TRUE; } } /* Look for a `Quiet' tooltype. */ if(FindToolType(Icon -> do_ToolTypes,"QUIET")) { if(!StartupFile[0]) DoIconify = TRUE; } /* Look for a `Behind' tooltype. */ if(FindToolType(Icon -> do_ToolTypes,"BEHIND")) KeepQuiet = TRUE; /* Free the icon. */ FreeDiskObject(Icon); } CloseLibrary(IconBase); IconBase = NULL; } /* Initialize this, so OpenAll will work with * correct data. */ TermPort = (struct TermPort *)FindPort("term Port"); /* We were called from Workbench. */ if(Result = OpenAll(ConfigPath)) { if(IntuitionBase && Result[0]) MyEasyRequest(NULL,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Result); CloseAll(TRUE); } else HandleInput(); } } return(RETURN_OK); } /* CloseLibs(): * * Plain and simple: close two libraries and clean up. */ STATIC VOID CloseLibs(VOID) { if(UtilityBase) { CloseLibrary(UtilityBase); UtilityBase = NULL; } if(WBenchMsg) CurrentDir(WBenchLock); if(DOSBase) { CloseLibrary(DOSBase); DOSBase = NULL; } #ifdef BETA StopBetaTask(); #endif /* BETA */ if(WBenchMsg) { Forbid(); ReplyMsg((struct Message *)WBenchMsg); } } /* ProcessCleanup(register __d1 BPTR SegList): * * Frees all resource the main process has allocated when * it exits. */ STATIC VOID __saveds __asm ProcessCleanup(register __d1 BPTR SegList) { CloseAll(FALSE); Forbid(); UnLoadSeg(SegList); CloseLibrary(DOSBase); DOSBase = NULL; } /* SegmentSplit(STRPTR Name,BYTE Pri,LONG StackSize,APTR Function): * * Create a new process from the current one. */ STATIC struct Process * __regargs SegmentSplit(STRPTR Name,BYTE Pri,LONG StackSize,APTR Function) { struct Process *Child; struct CommandLineInterface *CLI; CLI = (struct CommandLineInterface *)BADDR(((struct Process *)SysBase -> ThisTask) -> pr_CLI); Forbid(); Child = CreateNewProcTags( NP_CommandName, "term", NP_Name, Name, NP_Priority, Pri, NP_StackSize, StackSize, NP_Entry, Function, NP_Cli, TRUE, NP_ExitCode, ProcessCleanup, NP_ExitData, CLI -> cli_Module, TAG_DONE); if(Child) CLI -> cli_Module = NULL; Permit(); return(Child); } /* HandleInput(): * * This is our main input loop (check window & serial). */ VOID __saveds HandleInput() { STRPTR Error; BOOLEAN AlmostFinished = FALSE; ThisProcess = (struct Process *)SysBase -> ThisTask; /* Open the resources we need. */ if(!IntuitionBase) { STRPTR Result; if(Result = OpenAll(ConfigPath)) { if(IntuitionBase && Result[0]) MyEasyRequest(NULL,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Result); if(WBenchMsg) CloseAll(TRUE); return; } } if(DoIconify) { HandleIconify(); DoIconify = FALSE; if(MainTerminated) goto Stop; } #ifndef BETA if(!KeepQuiet) BumpWindow(Window); #endif /* BETA */ /* Set up the public screen data. */ PubScreenStuff(); /* Change program priority. */ SetTaskPri(ThisProcess,(LONG)Config -> MiscConfig -> Priority); BlockWindows(); /* Load the phone book. */ LoadPhonebook(LastPhone); /* Build new menu strip. */ if(Error = BuildMenu()) { if(IntuitionBase) MyEasyRequest(NULL,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Error); CloseAll(TRUE); return; } #ifdef BETA StopBetaTask(); if(!KeepQuiet) BumpWindow(Window); #endif /* BETA */ /* Show our business card. */ if(!StartupFile[0] && !KeepQuiet) { if(ShowAbout(TRUE)) while(HandleRexx()); } ReleaseWindows(); /* Don't do anything silly. */ KeepQuiet = FALSE; /* Initialize the modem. */ SerialCommand(Config -> ModemConfig -> ModemInit); /* Execute the startup macro (if any). */ if(Config -> CommandConfig -> StartupMacro[0]) SerialCommand(Config -> CommandConfig -> StartupMacro); LogAction(LocaleString(MSG_TERMMAIN_LOGMSG_PROGRAM_STARTED_TXT),TermName,TermDate); /* Go into input loop... */ Loop: while(!MainTerminated) { if(Recording) { if(RecordingLine) Status = STATUS_RECORDING_LINE; else Status = STATUS_RECORDING; } /* Handle the signal responses. */ HandleResponse(); if(RebuildMenu) { if(Error = BuildMenu()) { if(IntuitionBase) MyEasyRequest(NULL,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),Error); MainTerminated = TRUE; break; } RebuildMenu = FALSE; } /* Are we to run an ARexx script file? */ if(StartupFile[0]) { BlockWindows(); SendARexxCommand(StartupFile); ReleaseWindows(); StartupFile[0] = 0; } /* Are we to leave the main loop? */ if(MainTerminated) break; /* Make the user notice not too obvious events. */ if(FlowInfo . Changed) HandleFlowChange(); /* Are we no longer online? */ if(!Online && WasOnline) HandleOnlineCleanup(); /* Now for public screen mode changes. */ if(FixPubScreenMode) PubScreenStuff(); /* Now for window size changes. */ if(FixScreenSize) ScreenSizeStuff(); /* Somebody told us to re-open the display * (changed the terminal emulation/colour * mode, etc.). */ if(ResetDisplay) { if(!DisplayReset()) break; } /* Display the online cost. */ if(!Online && CurrentPay) { /* Reset the text rendering styles, font, etc. in * order to keep the following text from getting * illegible. */ SoftReset(); /* Display how much we expect * the user will have to pay for * this call. */ ConWrites(LocaleString(MSG_TERMMAIN_THIS_CALL_WILL_COST_YOU_TXT),CreateSum(CurrentPay,TRUE)); CurrentPay = 0; } /* Iconify the program? */ if(DoIconify) { HandleIconify(); if(MainTerminated) break; } /* Reset the serial driver? */ if(ResetSerial) { HandleSerialReset(); if(MainTerminated) break; } /* We are to release the serial.device (or * whatever we are using) for some reason. */ if(ReleaseSerial) { HandleSerialRelease(); if(MainTerminated) break; } /* Invoke the dialing function? */ if(DoDial != DIAL_IGNORE) { if(Online) { FreeDialList(FALSE); DoDial = DIAL_IGNORE; Forbid(); if(DialMsg) { DialMsg -> rm_Result1 = RC_WARN; DialMsg -> rm_Result2 = 0; ReplyMsg(DialMsg); DialMsg = NULL; } Permit(); } else { if(DoDial == DIAL_LIST) { BYTE OldStatus = Status; DoDial = DIAL_IGNORE; BlockWindows(); DialPanel(); FreeDialList(FALSE); Status = OldStatus; SetRedialMenu(); ReleaseWindows(); } else { DoDial = DIAL_IGNORE; HandleMenuCode(MEN_REDIAL,NULL); } } } /* Can we quit now? */ if(AlmostFinished && !CantQuit) break; } /* Don't exit until all background processes * have terminated. */ if(MainTerminated && CantQuit) { MainTerminated = FALSE; AlmostFinished = TRUE; goto Loop; } AlmostFinished = FALSE; /* User wants to quit term, so let's try to close * our magnificient screen and exit. */ Stop: if(Screen) { struct List *PubScreenList; struct PubScreenNode *ScreenNode; /* Lock the list of public screens. */ PubScreenList = LockPubScreenList(); /* Scan the list and try to find our * private node. */ for(ScreenNode = (struct PubScreenNode *)PubScreenList -> lh_Head ; ScreenNode -> psn_Node . ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode -> psn_Node . ln_Succ) { if(ScreenNode -> psn_Screen == Screen) break; } if(ScreenNode) { /* Okay, we know who and where we are, * check the number of visitor windows * currently open on our screen. */ if(ScreenNode -> psn_VisitorCount) { /* No chance, don't close * the screen now. */ UnlockPubScreenList(); BlockWindows(); MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),LocaleString(MSG_TERMMAIN_CANNOT_CLOSE_SCREEN_YET_TXT)); ReleaseWindows(); AlmostFinished = MainTerminated = FALSE; goto Loop; } } UnlockPubScreenList(); } /* Send the modem exit command, shut down the * serial.device and close all resources. */ SerialCommand(Config -> ModemConfig -> ModemExit); ClearSerial(); LogAction(LocaleString(MSG_TERMMAIN_LOGMSG_PROGRAM_TERMINATED_TXT)); Say(LocaleString(MSG_TERMMAIN_BYE_BYE_TXT)); if(Phonebook && PhoneSize) DeletePhonebook(Phonebook,PhoneSize,TRUE); if(!ThisProcess -> pr_CLI) CloseAll(TRUE); } /* SendInputTextBuffer(STRPTR Buffer,LONG Len,BOOL Bell): * * Transmit text the user typed or pasted via the * clipboard. */ STATIC VOID __regargs SendInputTextBuffer(STRPTR Buffer,LONG Len,BOOL Bell) { UBYTE Mask,c; if(Config -> SerialConfig -> StripBit8) Mask = 0x7F; else Mask = 0xFF; while(Len--) { switch(CharType[c = (*Buffer++) & Mask]) { case CHAR_ENTER: if(Status == STATUS_HOLDING) { if(Bell) BellSignal(); } else { switch(Config -> TerminalConfig -> SendLF) { case LF_ASLF: SerWrite("\n",1); break; case LF_ASLFCR: SerWrite("\n\r",2); break; } } break; case CHAR_RETURN: if(Status == STATUS_HOLDING) { if(Bell) BellSignal(); } else { switch(Config -> TerminalConfig -> SendCR) { case CR_ASCR: SerWrite("\r",1); break; case CR_ASCRLF: SerWrite("\r\n",2); break; } } break; /* Stop in/output. */ case CHAR_XON: if(Status == STATUS_HOLDING) { if(Bell) BellSignal(); } else { if(Config -> SerialConfig -> xONxOFF) Status = STATUS_HOLDING; if(Config -> SerialConfig -> PassThrough) SerWrite(&c,1); } break; /* Restart in/output. */ case CHAR_XOFF: if(Status == STATUS_HOLDING) Status = STATUS_READY; if(Config -> SerialConfig -> PassThrough) SerWrite(&c,1); break; /* Any other character. */ case CHAR_VANILLA: if(Status == STATUS_HOLDING) { if(Bell) BellSignal(); } else { if(Config -> TerminalConfig -> FontMode == FONT_IBM) { /* Convert special * Amiga characters into * alien IBM dialect. */ if(IBMConversion[c]) SerWrite(&IBMConversion[c],1); else SerWrite(&c,1); } else SerWrite(&c,1); } break; } } } /* HandleWindow(): * * This funny part checks the window(s) for incoming * user input. Menus are handled elsewhere. */ BYTE HandleWindow() { STATIC ULONG LastSeconds,LastMicros; struct IntuiMessage *Message; ULONG IClass,Code,Qualifier,Seconds,Micros; LONG MouseX,MouseY,Len,GadgetID; struct Gadget *Gadget; UBYTE Char,InputBuffer[257]; struct Window *IDCMPWindow; BOOLEAN Result = FALSE,ClickAndActivate = FALSE; /* Are we reading input from the clipboard? */ if(ClipInput) { WORD Len = GetClip(InputBuffer,256,FALSE); if(Len < 0) { CloseClip(); ClipInput = FALSE; if(ClipXerox) { if(Config -> ClipConfig -> InsertSuffix[0]) SerialCommand(Config -> ClipConfig -> InsertSuffix); ClipXerox = FALSE; } ClipPrefix = FALSE; } else { if(!ClipPrefix && ClipXerox) { if(Config -> ClipConfig -> InsertPrefix[0]) SerialCommand(Config -> ClipConfig -> InsertPrefix); ClipPrefix = TRUE; } if(Len > 0) SendInputTextBuffer(InputBuffer,Len,FALSE); Result = TRUE; } } /* Any news in the mail? */ if(Message = (struct IntuiMessage *)GetMsg(Window -> UserPort)) { /* A click into the window should activate it, but * we don't want to have the character snapping activated * under these conditions. In this case we rely upon * Intuition sending the IDCMP_ACTIVEWINDOW and * IDCMP_MOUSEBUTTONS event marked with the same * creation time stamp. Even if the Intuition * implementation should change no harm should * be done. */ Seconds = Message -> Seconds; Micros = Message -> Micros; if(Seconds == LastSeconds && Micros == LastMicros && Message -> IDCMPWindow == Window) { if(Message -> Class == IDCMP_ACTIVEWINDOW || Message -> Class == IDCMP_MOUSEBUTTONS) ClickAndActivate = TRUE; } LastSeconds = Seconds; LastMicros = Micros; /* Pick up the pieces. */ IClass = Message -> Class; Code = Message -> Code; Qualifier = Message -> Qualifier; Gadget = (struct Gadget *)Message -> IAddress; MouseX = Message -> MouseX; MouseY = Message -> MouseY; IDCMPWindow = Message -> IDCMPWindow; if(IClass == IDCMP_IDCMPUPDATE) GadgetID = GetTagData(GA_ID,0,(struct TagItem *)Gadget); if(IClass == IDCMP_RAWKEY) { /* Perform key conversion. */ if(XEmulatorBase) { if(Len = XEmulatorUserMon(XEM_IO,InputBuffer,256,Message)) Char = InputBuffer[0]; } else Char = KeyConvert(Message,InputBuffer,&Len); } ReplyMsg(Message); } else IClass = NULL; /* Did we get any information? */ if(IClass) { /* The following messages probably * originated from the fast! macro * panel. */ if(IDCMPWindow == FastWindow) { switch(IClass) { /* Close the window. */ case IDCMP_CLOSEWINDOW: CloseFastWindow(); return(TRUE); /* Window size has changed for some reason. */ case IDCMP_NEWSIZE: RefreshFastWindow(FALSE); return(TRUE); /* Some gadget was invoked. */ case IDCMP_GADGETUP: case IDCMP_GADGETDOWN: GadgetID = Gadget -> GadgetID; case IDCMP_MOUSEMOVE: case IDCMP_IDCMPUPDATE: HandleFastWindowGadget(IClass,Code,GadgetID); return(TRUE); } } /* Status window activated? */ if(IDCMPWindow == StatusWindow) { if(IClass == IDCMP_ACTIVEWINDOW && !Config -> ScreenConfig -> SplitStatus) NormalCursor(); if(IClass == IDCMP_CLOSEWINDOW) { Forbid(); ClrSignal(SIG_HANDSHAKE); Signal(StatusProcess,SIG_CLOSEWINDOW); Wait(SIG_HANDSHAKE); Permit(); ClearMenuStrip(StatusWindow); CloseWindowSafely(StatusWindow); StatusWindow = NULL; } } /* Main window message? */ if(IDCMPWindow == Window) { switch(IClass) { case IDCMP_INACTIVEWINDOW: HoldClick = FALSE; GhostCursor(); break; case IDCMP_ACTIVEWINDOW: NormalCursor(); break; case IDCMP_NEWSIZE: /* Is a window clipping region installed? */ if(ClipRegion) { struct Rectangle RegionRectangle; /* Install old region. */ InstallClipRegion(Window -> WLayer,OldRegion); /* Fill in the clipping rectangle. */ RegionRectangle . MinX = Window -> BorderLeft; RegionRectangle . MinY = Window -> BorderTop; RegionRectangle . MaxX = Window -> Width - (Window -> BorderRight + 1); RegionRectangle . MaxY = Window -> Height - (Window -> BorderBottom + 1); /* Clear previous clipping region. */ ClearRegion(ClipRegion); /* Set new clipping region. */ OrRectRegion(ClipRegion,&RegionRectangle); /* Install new clipping region. */ OldRegion = InstallClipRegion(Window -> WLayer,ClipRegion); } HandleMenuCode(MEN_RESET_TERMINAL,Qualifier); break; case IDCMP_CLOSEWINDOW: HandleMenuCode(MEN_QUIT,Qualifier); break; case IDCMP_MOUSEMOVE: if(HoldClick) { if(!Marking) SetMarker(ClickX,ClickY); else { MouseX -= WindowLeft; if(MouseX < 0) MouseX = 0; if(MouseX > WindowWidth - 1) MouseX = WindowWidth - 1; MouseY -= WindowTop; if(MouseY < 0) MouseY = 0; if(MouseY > WindowHeight - 1) MouseY = WindowHeight - 1; MoveMarker(MouseX,MouseY); } } break; case IDCMP_MOUSEBUTTONS: if((!ClickAndActivate || Code != SELECTDOWN) && (!XEmulatorBase || Config -> TerminalConfig -> EmulationMode != EMULATION_EXTERNAL)) { if(Code == SELECTUP) HoldClick = FALSE; if(Code == SELECTDOWN) { MouseX -= WindowLeft; if(MouseX < 0) MouseX = 0; if(MouseX > WindowWidth - 1) MouseX = WindowWidth - 1; MouseY -= WindowTop; if(MouseY < 0) MouseY = 0; if(MouseY > WindowHeight - 1) MouseY = WindowHeight - 1; HoldClick = TRUE; if(Qualifier & IEQUALIFIER_CONTROL) { WORD FirstX,FirstY; FirstX = MouseX / TextFontWidth; FirstY = MouseY / TextFontHeight; if(FirstX <= LastColumn && FirstY <= LastLine) { UBYTE Char; ObtainSemaphore(RasterSemaphore); Char = Raster[FirstY * RasterWidth + FirstX]; ReleaseSemaphore(RasterSemaphore); if(Char) { SerWrite(&Char,1); if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) { switch(Config -> TerminalConfig -> SendCR) { case CR_ASCR: SerWrite("\r",1); break; case CR_ASCRLF: SerWrite("\r\n",2); break; } } } } return(TRUE); } if((Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) && (Qualifier & IEQUALIFIER_LEFTBUTTON)) { WORD DeltaX,DeltaY; ObtainTerminal(); DeltaX = MouseX / TextFontWidth - CursorX; DeltaY = MouseY / TextFontHeight - CursorY; ReleaseTerminal(); if(DeltaX || DeltaY) { if(DeltaX > 0) { DeltaX++; while(DeltaX--) SerWrite("\33[C",3); } if(DeltaX < 0) { while(DeltaX++) SerWrite("\33[D",3); } if(DeltaY > 0) { DeltaY++; while(DeltaY--) SerWrite("\33[B",3); } if(DeltaY < 0) { while(DeltaY++) SerWrite("\33[A",3); } } return(TRUE); } ReportMouse(TRUE,Window); if(!FirstClick) { ULONG CurrentSecs,CurrentMicros; CurrentTime(&CurrentSecs,&CurrentMicros); FirstClick = TRUE; if(ABS(ClickX - MouseX) <= TextFontWidth && ABS(ClickY - MouseY) <= TextFontHeight && DoubleClick(ClickSecs,ClickMicros,CurrentSecs,CurrentMicros)) { MarkWord(ClickX,ClickY); return(TRUE); } else { CurrentTime(&ClickSecs,&ClickMicros); FirstClick = FALSE; ClickX = MouseX; ClickY = MouseY; } } else { CurrentTime(&ClickSecs,&ClickMicros); FirstClick = FALSE; ClickX = MouseX; ClickY = MouseY; } if(Marking) { if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) MoveMarker(MouseX,MouseY); else { DropMarker(); CurrentTime(&ClickSecs,&ClickMicros); FirstClick = FALSE; ClickX = MouseX; ClickY = MouseY; ReportMouse(TRUE,Window); } } } } break; } } /* Now for general information. */ switch(IClass) { case IDCMP_RAWKEY: /* This looks like a raw, or better, now cooked key. */ if(Len) { switch(CharType[Char]) { case CHAR_HELP: GuideDisplay(CONTEXT_MAIN); Len = 0; break; case CHAR_CURSOR: if(ClipInput) { CloseClip(); ClipInput = ClipXerox = ClipPrefix = FALSE; } /* If in cursor key applications mode, * send the corresponding string. */ if(Config -> EmulationConfig -> CursorMode == KEYMODE_APPLICATION) { STATIC STRPTR CursorTable[4] = { "\033OA", "\033OB", "\033OC", "\033OD" }; SerWrite(CursorTable[Char - CUP],3); } else { WORD QualType; /* Find the approriate qualifier. */ if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) QualType = 1; else { if(Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) QualType = 2; else { if(Qualifier & IEQUALIFIER_CONTROL) QualType = 3; else QualType = 0; } } /* Send the corresponding string. */ SerialCommand(CursorKeys -> Keys[QualType][Char - CUP]); } Len = 0; break; /* Any function key pressed? */ case CHAR_FUNCTION: if(ClipInput) { CloseClip(); ClipInput = ClipXerox = ClipPrefix = FALSE; } if(Qualifier & IEQUALIFIER_CONTROL) SerialCommand(MacroKeys -> Keys[3][Char - FN1]); else { if(Qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) SerialCommand(MacroKeys -> Keys[2][Char - FN1]); else { if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) SerialCommand(MacroKeys -> Keys[1][Char - FN1]); else SerialCommand(MacroKeys -> Keys[0][Char - FN1]); } } Len = 0; break; /* Anything else? */ default: if(Len == 1 && Char == '\r' && Recording && !RecordingLine && (Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))) { RememberInputText("\r",1); Len = 0; RecordingLine = TRUE; RememberResetInput(); RememberOutput = FALSE; RememberInput = TRUE; CheckItem(MEN_RECORD_LINE,TRUE); } if(Len == 1 && (Qualifier & IEQUALIFIER_NUMERICPAD) && (Config -> EmulationConfig -> NumericMode == KEYMODE_APPLICATION)) { STATIC STRPTR ApplicationTable[20][2] = { "0", "\033Op", "1", "\033Oq", "2", "\033Or", "3", "\033Os", "4", "\033Ot", "5", "\033Ou", "6", "\033Ov", "7", "\033Ow", "8", "\033Ox", "9", "\033Oy", "-", "\033Om", "+", "\033Ol", /* This should really be a comma */ ".", "\033On", "[", "\033OP", "{", "\033OP", "]", "\033OQ", "}", "\033OQ", "/", "\033OR", "*", "\033OS", "\r", "\033OM" }; WORD i; for(i = 0 ; i < 20 ; i++) { if(Char == ApplicationTable[i][0][0]) { if(ClipInput) { CloseClip(); ClipInput = ClipXerox = ClipPrefix = FALSE; } SerWrite(ApplicationTable[i][1],strlen(ApplicationTable[i][1])); Len = 0; break; } } } break; } /* Any characters to send? */ if(Len) SendInputTextBuffer(InputBuffer,Len,TRUE); } break; /* A menu item was selected. */ case IDCMP_MENUPICK: HandleMenu(Code,Qualifier); break; } return(TRUE); } return(Result); } /* HandleLocalDialList(BYTE ClearIt): * * Invoke the local dialing list or clear it. */ STATIC VOID __regargs HandleLocalDialList(BYTE ClearIt) { if(Menu) { struct MenuItem *DialItem; if(DialItem = FindThisItem(Menu,FirstDialMenu)) { if(Window) ClearMenuStrip(Window); if(StatusWindow) ClearMenuStrip(StatusWindow); if(FastWindow) ClearMenuStrip(FastWindow); do DialItem -> Flags &= ~CHECKED; while(DialItem = DialItem -> NextItem); if(Window) ResetMenuStrip(Window,Menu); if(StatusWindow) ResetMenuStrip(StatusWindow,Menu); if(FastWindow) ResetMenuStrip(FastWindow,Menu); } } if(LocalDialList) { if(LocalDialList -> lh_Head -> ln_Succ && !Online && !ClearIt) { FreeDialList(TRUE); DialList = LocalDialList; LocalDialList = NULL; LocalCount = -1; SetRedialMenu(); HandleMenuCode(MEN_REDIAL,NULL); } else { FreeList(LocalDialList); FreeVecPooled(LocalDialList); LocalDialList = NULL; LocalCount = -1; } } } /* HandleMenuCode(ULONG Code,ULONG Qualifier): * * Handle each function associated with a menu code. */ VOID __regargs HandleMenuCode(ULONG Code,ULONG Qualifier) { struct FileRequester *FileRequest; UBYTE DummyBuffer[MAX_FILENAME_LENGTH], *DummyChar; BYTE OldStatus = Status; BPTR SomeFile; APTR OldPtr; struct MenuItem *Item; switch(Code) { /* Save screen as IFF-ILBM file. */ case MEN_SAVE_AS_PICTURE: BlockWindows(); if(FileRequest = GetFile(Window,LocaleString(MSG_TERMMAIN_SAVE_SCREEN_IFF_TXT),"","",DummyBuffer,NULL,TRUE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SAVE_TXT),TRUE)) { if(!SaveWindow(DummyBuffer,Window)) ShowError(Window,ERR_SAVE_ERROR,IoErr(),DummyBuffer); FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Save screen as ASCII file. */ case MEN_SAVE_AS_TEXT: BlockWindows(); if(FileRequest = GetFile(Window,LocaleString(MSG_TERMMAIN_SAVE_SCREEN_ASCII_TXT),"","",DummyBuffer,NULL,TRUE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SAVE_TXT),FALSE)) { LONG Error = 0; if(GetFileSize(DummyBuffer)) { switch(MyEasyRequest(Window,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_TXT),LocaleString(MSG_GLOBAL_CREATE_APPEND_CANCEL_TXT),DummyBuffer)) { case 1: SomeFile = Open(DummyBuffer,MODE_NEWFILE); break; case 2: if(SomeFile = Open(DummyBuffer,MODE_READWRITE)) { if(Seek(SomeFile,0,OFFSET_END) == -1) { Close(SomeFile); SomeFile = NULL; } } break; case 0: SomeFile = ~0; break; } } else SomeFile = Open(DummyBuffer,MODE_NEWFILE); if(SomeFile) { if(SomeFile != ~0) { LONG i,j; UBYTE *Buffer; for(i = 0 ; i < RasterHeight ; i++) { Buffer = &Raster[i * RasterWidth]; j = LastColumn; while(j >= 0 && Buffer[j] == ' ') j--; if(j >= 0) { SetIoErr(0); if(FWrite(SomeFile,Buffer,j + 1,1) < 1) { Error = IoErr(); break; } } SetIoErr(0); if(FWrite(SomeFile,"\n",1,1) < 1) { Error = IoErr(); break; } } Close(SomeFile); AddProtection(DummyBuffer,FIBF_EXECUTE); if(Config -> MiscConfig -> CreateIcons) AddIcon(DummyBuffer,FILETYPE_TEXT,TRUE); } } else Error = IoErr(); if(Error) ShowError(Window,ERR_SAVE_ERROR,Error,DummyBuffer); FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Print the screen (pure ASCII). */ case MEN_PRINT_SCREEN: BlockWindows(); if(RasterEnabled) PrintSomething(PRINT_SCREEN); else MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_NO_DATA_TO_PRINT_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); ReleaseWindows(); break; /* Print the clipboard contents. */ case MEN_PRINT_CLIP: BlockWindows(); PrintSomething(PRINT_CLIP); ReleaseWindows(); break; /* Open/close the terminal capture file. */ case MEN_CAPTURE_TO_FILE: if(FileCapture) CloseFileCapture(); else OpenFileCapture(); break; /* Start/terminate the printer * capture. */ case MEN_CAPTURE_TO_PRINTER: if(PrinterCapture) ClosePrinterCapture(TRUE); else OpenPrinterCapture(FALSE); break; /* Iconify the program. */ case MEN_ICONIFY: if(Online && Config -> MiscConfig -> ReleaseDevice && !(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))) { if(!MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_YOU_ARE_STILL_ONLINE_TXT),LocaleString(MSG_GLOBAL_YES_NO_TXT))) break; } DoIconify = TRUE; break; /* Say who we are. */ case MEN_ABOUT: BlockWindows(); #ifdef DATAFEED { extern BPTR DataFeed; if(DataFeed) { Close(DataFeed); DataFeed = NULL; } if(FileRequest = GetFile(Window,"Select terminal test file","","",DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SELECT_TXT),FALSE)) { if(GetFileSize(DummyBuffer)) { if(DataFeed = Open(DummyBuffer,MODE_OLDFILE)) { if(Kick30) SetVBuf(DataFeed,NULL,2,8192); } } FreeAslRequest(FileRequest); } } #else ShowAbout(FALSE); #endif /* DATAFEED */ ReleaseWindows(); break; /* Terminate the program. */ case MEN_QUIT: if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) MainTerminated = TRUE; else { STRPTR Buffer; LONG OldLen,Len = strlen(LocaleString(MSG_TERMMAIN_REALLY_QUIT_TXT)) + 3; OldLen = Len; if(Online) Len += strlen(LocaleString(MSG_WAIT_PROGRAM_IS_STILL_ONLINE_TXT)) + 4; if(BufferChanged) Len += strlen(LocaleString(MSG_WAIT_REVIEW_BUFFER_NOT_SAVED_TXT)) + 4; if(ConfigChanged) Len += strlen(LocaleString(MSG_WAIT_CONFIGURATION_HAS_BEEN_CHANGED_TXT)) + 4; if(PhonebookChanged) Len += strlen(LocaleString(MSG_WAIT_PHONEBOOK_NOT_SAVED_TXT)) + 4; if(TranslationChanged) Len += strlen(LocaleString(MSG_WAIT_TRANSLATION_TABLES_CHANGED_TXT)) + 4; if(MacroChanged) Len += strlen(LocaleString(MSG_WAIT_MACRO_KEYS_CHANGED_TXT)) + 4; if(CursorKeysChanged) Len += strlen(LocaleString(MSG_WAIT_CURSOR_KEYS_CHANGED_TXT)) + 4; if(FastMacrosChanged) Len += strlen(LocaleString(MSG_WAIT_FAST_MACROS_CHANGED_TXT)) + 4; if(HotkeysChanged) Len += strlen(LocaleString(MSG_WAIT_HOTKEYS_CHANGED_TXT)) + 4; if(SpeechChanged) Len += strlen(LocaleString(MSG_WAIT_SPEECH_SETTINGS_CHANGED_TXT)) + 4; if(SoundChanged) Len += strlen(LocaleString(MSG_WAIT_SOUND_SETTINGS_CHANGED_TXT)) + 4; BlockWindows(); OldPtr = ThisProcess -> pr_WindowPtr; ThisProcess -> pr_WindowPtr = (APTR)Window; if(OldLen != Len) { if(Buffer = (STRPTR)AllocVecPooled(Len,MEMF_ANY)) { SPrintf(Buffer,"%s\n\n",LocaleString(MSG_TERMMAIN_REALLY_QUIT_TXT)); if(Online) { SPrintf(SharedBuffer," · %s\n",LocaleString(MSG_WAIT_PROGRAM_IS_STILL_ONLINE_TXT)); strcat(Buffer,SharedBuffer); } if(BufferChanged) { SPrintf(SharedBuffer," · %s\n",LocaleString(MSG_WAIT_REVIEW_BUFFER_NOT_SAVED_TXT)); strcat(Buffer,SharedBuffer); } if(ConfigChanged) { SPrintf(SharedBuffer," · %s\n",LocaleString(MSG_WAIT_CONFIGURATION_HAS_BEEN_CHANGED_TXT)); strcat(Buffer,SharedBuffer); } if(PhonebookChanged) { SPrintf(SharedBuffer," · %s\n",LocaleString(MSG_WAIT_PHONEBOOK_NOT_SAVED_TXT)); strcat(Buffer,SharedBuffer); } if(TranslationChanged) { SPrintf(SharedBuffer," · %s\n",LocaleString(MSG_WAIT_TRANSLATION_TABLES_CHANGED_TXT)); strcat(Buffer,SharedBuffer); } if(MacroChanged) { SPrintf(SharedBuffer," · %s\n",LocaleString(MSG_WAIT_MACRO_KEYS_CHANGED_TXT)); strcat(Buffer,SharedBuffer); } if(CursorKeysChanged) { SPrintf(SharedBuffer," · %s\n",LocaleString(MSG_WAIT_CURSOR_KEYS_CHANGED_TXT)); strcat(Buffer,SharedBuffer); } if(FastMacrosChanged) { SPrintf(SharedBuffer," · %s\n",LocaleString(MSG_WAIT_FAST_MACROS_CHANGED_TXT)); strcat(Buffer,SharedBuffer); } if(HotkeysChanged) { SPrintf(SharedBuffer," · %s\n",LocaleString(MSG_WAIT_HOTKEYS_CHANGED_TXT)); strcat(Buffer,SharedBuffer); } if(SpeechChanged) { SPrintf(SharedBuffer," · %s\n",LocaleString(MSG_WAIT_SPEECH_SETTINGS_CHANGED_TXT)); strcat(Buffer,SharedBuffer); } if(MyEasyRequest(Window,Buffer,LocaleString(MSG_GLOBAL_YES_NO_TXT))) MainTerminated = TRUE; FreeVecPooled(Buffer); } else MainTerminated = TRUE; } else MainTerminated = TRUE; ThisProcess -> pr_WindowPtr = OldPtr; ReleaseWindows(); } break; /* Feed the contents of the clipboard * into the input stream. */ case MEN_PASTE: if(!OpenClip(Config -> ClipConfig -> ClipboardUnit)) { ClipInput = TRUE; if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) ClipXerox = TRUE; } else ClipInput = FALSE; break; case MEN_COPY: if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) ClipMarker(TRUE); else ClipMarker(FALSE); break; case MEN_CLEAR: DropMarker(); break; /* Execute an AmigaDOS command. */ case MEN_EXECUTE_DOS_COMMAND: BlockWindows(); /* Enter the name of the command. */ if(GetString(TRUE,FALSE,0,LocaleString(MSG_TERMMAIN_ENTER_AMIGADOS_COMMAND_TXT),AmigaDOSCommandBuffer)) SendAmigaDOSCommand(AmigaDOSCommandBuffer); ReleaseWindows(); break; /* Execute an ARexx script command. */ case MEN_EXECUTE_REXX_COMMAND: BlockWindows(); /* Get the rexx file name/program. */ if(GetString(TRUE,FALSE,0,LocaleString(MSG_TERMMAIN_ENTER_AREXX_COMMAND_TXT),ARexxCommandBuffer)) SendARexxCommand(ARexxCommandBuffer); ReleaseWindows(); break; /* Turn recording on/off. */ case MEN_RECORD: if(GetItem(MEN_RECORD)) { if(!Recording) { if(CreateRecord(CurrentBBSName[0] ? CurrentBBSName : LocaleString(MSG_SCREENPANEL_UNKNOWN_TXT))) { RememberResetOutput(); RememberResetInput(); RememberOutput = TRUE; Recording = TRUE; RecordingLine = FALSE; OnItem(MEN_RECORD_LINE); } } } else { if(Recording) { FinishRecord(); RememberOutput = FALSE; RememberInput = FALSE; Recording = FALSE; RecordingLine = FALSE; OffItem(MEN_RECORD_LINE); } } break; case MEN_RECORD_LINE: if(Recording) { if(GetItem(MEN_RECORD)) { if(!RecordingLine) { RecordingLine = TRUE; RememberResetInput(); RememberOutput = FALSE; RememberInput = TRUE; } } else { if(RecordingLine) { RememberSpill(); RecordingLine = FALSE; RememberOutput = TRUE; RememberInput = FALSE; } } } break; case MEN_DISABLE_TRAPS: if(Item = FindThisItem(Menu,MEN_DISABLE_TRAPS)) { ObtainSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore); if(!(Item -> Flags & CHECKED) && GenericListTable[GLIST_TRAP] -> ListHeader . mlh_Head -> mln_Succ) WatchTraps = TRUE; else WatchTraps = FALSE; ReleaseSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore); } break; /* Edit the trap settings? */ case MEN_EDIT_TRAPS: BlockWindows(); TrapPanel(); if(Item = FindThisItem(Menu,MEN_DISABLE_TRAPS)) { if(WatchTraps) Item -> Flags &= ~CHECKED; else Item -> Flags |= CHECKED; } ReleaseWindows(); break; /* Set the name we will use to open the * default console output window for * AmigaDOS commands and ARexx scripts. */ case MEN_SET_CONSOLE: BlockWindows(); if(GetString(FALSE,FALSE,0,LocaleString(MSG_TERMMAIN_SET_CONSOLE_WINDOW_TXT),WindowName)) SetEnvDOS("TERMWINDOW",WindowName); ReleaseWindows(); break; /* Open the phonebook and dial the * list of entries the user will select. */ case MEN_PHONEBOOK: BlockWindows(); HandleLocalDialList(TRUE); while(PhonePanel()) { if(!DialPanel()) { Status = OldStatus; break; } Status = OldStatus; } SetRedialMenu(); ReleaseWindows(); break; /* Redial those dial list entries which * we were unable to connect. */ case MEN_REDIAL: BlockWindows(); HandleLocalDialList(TRUE); do { if(!DialPanel()) { Status = OldStatus; break; } Status = OldStatus; } while(PhonePanel()); SetRedialMenu(); ReleaseWindows(); break; /* Dial a single number. */ case MEN_DIAL_NUMBER: BlockWindows(); HandleLocalDialList(TRUE); DummyBuffer[0] = 0; if(GetString(FALSE,FALSE,0,LocaleString(MSG_TERMMAIN_ENTER_PHONE_NUMBER_TXT),DummyBuffer)) { if(DummyBuffer[0]) { struct List *LocalList; if(LocalList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY|MEMF_CLEAR)) { struct PhoneNode *DialNode; LONG Len = strlen(DummyBuffer); NewList(LocalList); if(DialNode = (struct PhoneNode *)AllocVecPooled(sizeof(struct PhoneNode) + Len + 1,MEMF_ANY|MEMF_CLEAR)) { DialNode -> VanillaNode . ln_Name = (char *)(DialNode + 1); strcpy(DialNode -> VanillaNode . ln_Name,DummyBuffer); AddTail(LocalList,&DialNode -> VanillaNode); FreeDialList(TRUE); DialList = LocalList; DialPanel(); Status = OldStatus; } else FreeVecPooled(LocalList); } } } SetRedialMenu(); ReleaseWindows(); break; /* Send a break across the serial line. */ case MEN_SEND_BREAK: SendBreak(); break; /* Hang up the phone line. */ case MEN_HANG_UP: BlockWindows(); if(DialMsg) { DialMsg -> rm_Result1 = RC_WARN; DialMsg -> rm_Result2 = 0; ReplyMsg(DialMsg); DialMsg = NULL; } HangUp(); /* Remember online state. */ WasOnline = Online; /* We are no longer online. */ Online = FALSE; /* Clear the password. */ Password[0] = 0; UserName[0] = 0; CurrentBBSName[0] = 0; CurrentBBSComment[0] = 0; CurrentBBSNumber[0] = 0; /* Reset time limit. */ LimitCount = -1; /* Note the last action. */ if(CurrentPay) { /* Reset the text rendering styles, font, etc. in * order to keep the following text from getting * illegible. */ SoftReset(); /* Display how much we expect * the user will have to pay for * this call. */ ConWrites(LocaleString(MSG_TERMMAIN_THIS_CALL_WILL_COST_YOU_TXT),CreateSum(CurrentPay,TRUE)); LogAction(LocaleString(MSG_TERMMAIN_LOGMSG_HANG_UP_COST_TXT),CreateSum(CurrentPay,TRUE)); CurrentPay = 0; } else LogAction(LocaleString(MSG_TERMMAIN_LOGMSG_HANG_UP_TXT)); SoundPlay(SOUND_DISCONNECT); ReleaseWindows(); /* Execute logoff macro. */ if(Config -> CommandConfig -> LogoffMacro[0] && WasOnline) SerialCommand(Config -> CommandConfig -> LogoffMacro); /* Update the logfile. */ StopCall(FALSE); /* Don't execute the logoff macro twice. */ WasOnline = FALSE; ChosenEntry = NULL; /* Enable the dialing functions. */ SetDialMenu(TRUE); /* Previous configuration available? */ if(BackupConfig) { /* Remember old configuration. */ SaveConfig(Config,PrivateConfig); /* Copy configuration. */ SaveConfig(BackupConfig,Config); /* Set up new configuration. */ ConfigSetup(); /* Free old configuration. */ DeleteConfiguration(BackupConfig); BackupConfig = NULL; } if(Config -> ModemConfig -> RedialAfterHangup) { if(DialList) { if(DialList -> lh_Head -> ln_Succ) DoDial = DIAL_REDIAL; } } break; /* Wait a bit... */ case MEN_WAIT: { struct Window *ReqWindow; struct EasyStruct Easy; Easy . es_StructSize = sizeof(struct EasyStruct); Easy . es_Flags = NULL; Easy . es_Title = (UBYTE *)LocaleString(MSG_TERMAUX_TERM_REQUEST_TXT); Easy . es_GadgetFormat = (UBYTE *)LocaleString(MSG_GLOBAL_CONTINUE_TXT); Easy . es_TextFormat = (UBYTE *)LocaleString(MSG_TERMMAIN_WAITING_TXT); BlockWindows(); if(ReqWindow = BuildEasyRequest(Window,&Easy,NULL)) { ULONG Signals; BYTE Done = FALSE; /* Don't echo serial output. */ Quiet = TRUE; do { SerWrite(" \b",2); HandleSerial(); StartTime(1,0); Signals = Wait(SIG_TIMER | PORTMASK(ReqWindow -> UserPort)); if(Signals & SIG_TIMER) WaitIO(TimeRequest); if(Signals & PORTMASK(ReqWindow -> UserPort)) { if(!SysReqHandler(ReqWindow,NULL,FALSE)) { Done = TRUE; if(!CheckIO(TimeRequest)) AbortIO(TimeRequest); WaitIO(TimeRequest); } } } while(!Done); Quiet = FALSE; FreeSysRequest(ReqWindow); } ReleaseWindows(); } break; /* Flush the serial buffers. */ case MEN_FLUSH_BUFFER: ClearSerial(); RestartSerial(FALSE); break; /* Release the serial device for other * applications. */ case MEN_RELEASE_DEVICE: ReleaseSerial = TRUE; break; case MEN_UPLOAD_ASCII: BlockWindows(); if(ChangeProtocol(Config -> TransferConfig -> ASCIIUploadLibrary)) { BinaryTransfer = FALSE; StartXprSend(TRANSFER_ASCII,TRUE); BinaryTransfer = TRUE; } ResetProtocol(); ReleaseWindows(); break; case MEN_DOWNLOAD_ASCII: BlockWindows(); if(ChangeProtocol(Config -> TransferConfig -> ASCIIDownloadLibrary)) { BinaryTransfer = FALSE; StartXprReceive(TRANSFER_ASCII,NULL,TRUE); BinaryTransfer = TRUE; } ResetProtocol(); ReleaseWindows(); break; case MEN_UPLOAD_TEXT: BlockWindows(); if(ChangeProtocol(Config -> TransferConfig -> TextUploadLibrary)) { BinaryTransfer = FALSE; StartXprSend(TRANSFER_TEXT,TRUE); BinaryTransfer = TRUE; } ResetProtocol(); ReleaseWindows(); break; case MEN_DOWNLOAD_TEXT: BlockWindows(); if(ChangeProtocol(Config -> TransferConfig -> TextDownloadLibrary)) { BinaryTransfer = FALSE; StartXprReceive(TRANSFER_TEXT,NULL,TRUE); BinaryTransfer = TRUE; } ResetProtocol(); ReleaseWindows(); break; /* Edit and transfer a file. */ case MEN_EDIT_AND_UPLOAD_TEXT: BlockWindows(); if(!Config -> PathConfig -> Editor[0]) GetString(TRUE,FALSE,0,LocaleString(MSG_TERMMAIN_ENTER_NAME_OF_EDITOR_TO_USE_TXT),Config -> PathConfig -> Editor); if(Config -> PathConfig -> Editor[0]) { if(FileRequest = GetFile(Window,LocaleString(MSG_TERMMAIN_EDIT_AND_TRANSFER_FILE_TXT),"","",DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_TERMMAIN_EDIT_TXT),TRUE)) { UBYTE CompoundName[512]; strcpy(CompoundName,Config -> PathConfig -> Editor); strcat(CompoundName," \""); strcat(CompoundName,DummyBuffer); strcat(CompoundName,"\""); SystemTags(CompoundName, SYS_UserShell, TRUE, TAG_DONE); BumpWindow(Window); FreeAslRequest(FileRequest); if(GetFileSize(DummyBuffer)) { BinaryTransfer = FALSE; switch(MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_TRANSFER_FILE_AS_TXT),LocaleString(MSG_TERMMAIN_ASCII_UPLOAD_CANCEL_TXT),FilePart(DummyBuffer))) { case 1: if(ChangeProtocol(Config -> TransferConfig -> ASCIIUploadLibrary)) SendTextFile(TRANSFER_ASCII,DummyBuffer); ResetProtocol(); break; case 2: if(ChangeProtocol(Config -> TransferConfig -> TextUploadLibrary)) SendTextFile(TRANSFER_TEXT,DummyBuffer); ResetProtocol(); break; } BinaryTransfer = TRUE; } } } ReleaseWindows(); break; case MEN_UPLOAD_BINARY: BlockWindows(); if(ChangeProtocol(Config -> TransferConfig -> BinaryUploadLibrary)) { BinaryTransfer = TRUE; StartXprSend(TRANSFER_BINARY,TRUE); } ResetProtocol(); ReleaseWindows(); break; /* Download some files. */ case MEN_DOWNLOAD_BINARY: BlockWindows(); if(ChangeProtocol(Config -> TransferConfig -> BinaryDownloadLibrary)) { BinaryTransfer = TRUE; StartXprReceive(TRANSFER_BINARY,NULL,TRUE); } ResetProtocol(); ReleaseWindows(); break; /* Clear the contents of the scrollback * buffer. */ case MEN_CLEAR_BUFFER: if(Lines) { BlockWindows(); if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) { FreeBuffer(); TerminateBuffer(); } else { if(MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_BUFFER_STILL_HOLDS_LINES_TXT),LocaleString(MSG_GLOBAL_YES_NO_TXT),Lines)) { FreeBuffer(); TerminateBuffer(); } } ReleaseWindows(); } break; /* Display the scrollback buffer. * Notify the scrollback task or * fire it off if approriate. */ case MEN_DISPLAY_BUFFER: if(!LaunchBuffer()) { BlockWindows(); MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_UNABLE_TO_CREATE_BUFFER_TASK_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); ReleaseWindows(); } break; /* Close the buffer display. */ case MEN_CLOSE_BUFFER: if(BufferTask) { Forbid(); Signal(BufferTask,SIG_KILL); ClrSignal(SIG_HANDSHAKE); Wait(SIG_HANDSHAKE); Permit(); } break; /* Is the buffer to be frozen? */ case MEN_FREEZE_BUFFER: BufferFrozen ^= TRUE; CheckItem(MEN_FREEZE_BUFFER,BufferFrozen); Forbid(); ConOutputUpdate(); Permit(); break; /* Load the buffer contents from a file. */ case MEN_OPEN_BUFFER: BlockWindows(); if(FileRequest = GetFile(Window,LocaleString(MSG_TERMMAIN_LOAD_BUFFER_TXT),"","",DummyBuffer,NULL,FALSE,FALSE,FALSE,LocaleString(MSG_GLOBAL_LOAD_TXT),FALSE)) { if(GetFileSize(DummyBuffer)) { if(SomeFile = Open(DummyBuffer,MODE_OLDFILE)) { if(Lines) { switch(MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_BUFFER_STILL_HOLDS_LINES_TXT),LocaleString(MSG_TERMMAIN_DISCARD_APPPEND_CANCEL_TXT),Lines)) { case 1: FreeBuffer(); break; case 2: break; case 0: Close(SomeFile); SomeFile = NULL; break; } } if(SomeFile) { LONG Len; LineRead(NULL,NULL,NULL); while((Len = LineRead(SomeFile,DummyBuffer,80)) > 0) StoreBuffer(DummyBuffer,Len); Close(SomeFile); BufferChanged = TRUE; } } else ShowError(Window,ERR_LOAD_ERROR,IoErr(),DummyBuffer); } FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Save the contents of the scrollback * buffer to a file (line by line). */ case MEN_SAVE_BUFFER_AS: BlockWindows(); if(!Lines || !BufferLines) MyEasyRequest(Window,LocaleString(MSG_GLOBAL_NOTHING_IN_THE_BUFFER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); else { if(FileRequest = GetFile(Window,LocaleString(MSG_TERMMAIN_SAVE_BUFFER_TXT),Config -> CaptureConfig -> BufferPath,"",DummyBuffer,NULL,TRUE,FALSE,FALSE,LocaleString(MSG_GLOBAL_SAVE_TXT),FALSE)) { LONG Error = 0; SomeFile = NULL; /* If the file we are about * to create already exists, * ask the user whether we are * to create, append or skip * the file. */ if(GetFileSize(DummyBuffer)) { switch(MyEasyRequest(Window,LocaleString(MSG_GLOBAL_FILE_ALREADY_EXISTS_TXT),LocaleString(MSG_GLOBAL_CREATE_APPEND_CANCEL_TXT),DummyBuffer)) { case 1: SomeFile = Open(DummyBuffer,MODE_NEWFILE); break; case 2: if(SomeFile = Open(DummyBuffer,MODE_READWRITE)) { if(Seek(SomeFile,0,OFFSET_END) == -1) { Close(SomeFile); SomeFile = NULL; } } break; } } else SomeFile = Open(DummyBuffer,MODE_NEWFILE); if(SomeFile) { LONG i,Len; /* Obtain the semaphore required * to gain access to the line buffer */ ObtainSemaphore(BufferSemaphore); for(i = 0 ; i < Lines ; i++) { Len = BufferLines[i][-1]; if(Len) { SetIoErr(0); if(FWrite(SomeFile,BufferLines[i],Len,1) < 1) { Error = IoErr(); break; } } SetIoErr(0); if(FPrintf(SomeFile,"\n") < 1) { Error = IoErr(); break; } } ReleaseSemaphore(BufferSemaphore); Close(SomeFile); AddProtection(DummyBuffer,FIBF_EXECUTE); if(Config -> MiscConfig -> CreateIcons) AddIcon(DummyBuffer,FILETYPE_TEXT,TRUE); BufferChanged = FALSE; } else Error = IoErr(); if(Error) ShowError(Window,ERR_SAVE_ERROR,IoErr(),DummyBuffer); FreeAslRequest(FileRequest); } } ReleaseWindows(); break; /* Simply clear the screen and move the * cursor to its home position. */ case MEN_CLEAR_SCREEN: if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL) XEmulatorClearConsole(XEM_IO); else { DropMarker(); ConBypass("\033[2J\033[H",-1); } break; /* Reset the current text rendering font. */ case MEN_RESET_FONT: if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL) XEmulatorResetCharset(XEM_IO); else { DropMarker(); CurrentFont = TextFont; SetFont(RPort,CurrentFont); ConOutputUpdate(); } break; /* Reset the display styles and restore * the colours. */ case MEN_RESET_STYLES: if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL) XEmulatorResetTextStyles(XEM_IO); else { DropMarker(); ConBypass("\033[0m",-1); ObtainTerminal(); ClearCursor(); Config -> EmulationConfig -> FontScale = SCALE_NORMAL; FgPen = GetPenIndex(SafeTextPen); BgPen = 0; if(ReadAPen(RPort) != MappedPens[0][FgPen]) SetAPen(RPort,MappedPens[0][FgPen]); if(ReadBPen(RPort) != MappedPens[0][BgPen]) SetBPen(RPort,MappedPens[0][BgPen]); SetWrMsk(RPort,DepthMask); ConFontScaleUpdate(); DrawCursor(); ReleaseTerminal(); } break; /* Reset the whole terminal. */ case MEN_RESET_TERMINAL: if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL) XEmulatorResetConsole(XEM_IO); else { FreeMarker(); ConBypass("\033c",-1); } break; case MEN_SET_EMULATION: BlockWindows(); if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL) { OptionTitle = LocaleString(MSG_TERMMAIN_EMULATION_PREFERENCES_TXT); XEmulatorOptions(XEM_IO); if(NewOptions) { SetEmulatorOptions(XEM_PREFS_SAVE); NewOptions = FALSE; } OptionTitle = NULL; } else EmulationPanel(Config,NULL); ReleaseWindows(); break; /* Set the serial preferences. */ case MEN_SERIAL: BlockWindows(); if(SerialPanel(Config,NULL)) { ConfigSetup(); ConfigChanged = TRUE; } ReleaseWindows(); break; /* Set the modem preferences. */ case MEN_MODEM: BlockWindows(); if(ModemPanel(Config,NULL)) { FlowInit(TRUE); ConfigChanged = TRUE; } ReleaseWindows(); break; /* Set the screen preferences. */ case MEN_SCREEN: BlockWindows(); if(ScreenPanel(Config,NULL)) { if(memcmp(PrivateConfig -> ScreenConfig -> Colours,Config -> ScreenConfig -> Colours,sizeof(UWORD) * 16)) { switch(Config -> ScreenConfig -> ColourMode) { case COLOUR_EIGHT: CopyMem(Config -> ScreenConfig -> Colours,ANSIColours,16 * sizeof(UWORD)); break; case COLOUR_SIXTEEN: CopyMem(Config -> ScreenConfig -> Colours,EGAColours,16 * sizeof(UWORD)); break; case COLOUR_AMIGA: CopyMem(Config -> ScreenConfig -> Colours,DefaultColours,16 * sizeof(UWORD)); break; case COLOUR_MONO: CopyMem(Config -> ScreenConfig -> Colours,AtomicColours,16 * sizeof(UWORD)); break; } } ConfigSetup(); ConfigChanged = TRUE; } else { if(memcmp(PrivateConfig -> ScreenConfig -> Colours,Config -> ScreenConfig -> Colours,sizeof(UWORD) * 16)) { switch(Config -> ScreenConfig -> ColourMode) { case COLOUR_EIGHT: CopyMem(Config -> ScreenConfig -> Colours,ANSIColours,16 * sizeof(UWORD)); break; case COLOUR_SIXTEEN: CopyMem(Config -> ScreenConfig -> Colours,EGAColours,16 * sizeof(UWORD)); break; case COLOUR_AMIGA: CopyMem(Config -> ScreenConfig -> Colours,DefaultColours,16 * sizeof(UWORD)); break; case COLOUR_MONO: CopyMem(Config -> ScreenConfig -> Colours,AtomicColours,16 * sizeof(UWORD)); break; } ConfigChanged = TRUE; } } ReleaseWindows(); break; /* Set the terminal preferences. */ case MEN_TERMINAL: BlockWindows(); if(TerminalPanel(Config,NULL)) { ConfigSetup(); ConfigChanged = TRUE; } ReleaseWindows(); break; /* Set the clipboard preferences. */ case MEN_CLIPBOARD: BlockWindows(); if(ClipPanel(Config,NULL)) { ConfigSetup(); ConfigChanged = TRUE; } ReleaseWindows(); break; /* Set the capture preferences. */ case MEN_CAPTURE: BlockWindows(); if(CapturePanel(Config,NULL)) { ConfigSetup(); ConfigChanged = TRUE; } ReleaseWindows(); break; /* Set the command preferences. */ case MEN_COMMANDS: BlockWindows(); if(CommandPanel(Config,NULL)) ConfigChanged = TRUE; ReleaseWindows(); break; /* Set the miscellaneous preferences. */ case MEN_MISC: BlockWindows(); if(MiscPanel(Config,NULL)) { ConfigSetup(); ConfigChanged = TRUE; } ReleaseWindows(); break; /* Set the path settings. */ case MEN_PATH: BlockWindows(); if(PathPanel(Config,NULL)) ConfigChanged = TRUE; ReleaseWindows(); break; /* Set the file transfer options. */ case MEN_TRANSFER: BlockWindows(); XprIO -> xpr_filename = NULL; /* Set up the library options. */ if(XProtocolBase) { XPRCommandSelected = FALSE; ClearSerial(); NewOptions = FALSE; TransferBits = XProtocolSetup(XprIO); RestartSerial(FALSE); DeleteTransferPanel(TRUE); /* Successful? */ if(!XPRCommandSelected) { if(!(TransferBits & XPRS_SUCCESS)) { MyEasyRequest(Window,LocaleString(MSG_GLOBAL_FAILED_TO_SET_UP_PROTOCOL_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),LastXprLibrary); CloseLibrary(XProtocolBase); XProtocolBase = NULL; LastXprLibrary[0] = 0; TransferBits = 0; SetTransferMenu(FALSE); } else SaveProtocolOpts(); } } ReleaseWindows(); break; /* Set the file transfer procol settings. */ case MEN_TRANSFER_PROTOCOL: BlockWindows(); if(LibPanel(Config,NULL)) { ConfigSetup(); ConfigChanged = TRUE; } ReleaseWindows(); break; /* Set the translation tables. */ case MEN_TRANSLATION: BlockWindows(); TranslationChanged |= TranslationPanel(); /* Choose the right console write routine. */ ConOutputUpdate(); ReleaseWindows(); break; /* Set the keyboard macros. */ case MEN_MACROS: BlockWindows(); if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL) { XEmulatorMacroKeyFilter(XEM_IO,NULL); MacroPanel(MacroKeys); SetupXEM_MacroKeys(MacroKeys); } else MacroPanel(MacroKeys); ReleaseWindows(); break; /* Set the cursor keys. */ case MEN_CURSORKEYS: BlockWindows(); CursorPanel(CursorKeys); ReleaseWindows(); break; /* Set the fast macros. */ case MEN_FAST_MACROS: BlockWindows(); FastMacroPanel(); ReleaseWindows(); break; /* Set the hotkey preferences. */ case MEN_HOTKEYS: BlockWindows(); if(HotkeyPanel(&Hotkeys)) { if(!SetupCx()) MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_SET_UP_HOTKEYS_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); } ReleaseWindows(); break; /* Set the speech preferences. */ case MEN_SPEECH: BlockWindows(); SpeechPanel(); ReleaseWindows(); break; /* Set the sound preferences. */ case MEN_SOUND: BlockWindows(); if(SoundPanel(&SoundConfig)) SoundInit(); ReleaseWindows(); break; /* Open the preferences settings. */ case MEN_OPEN_SETTINGS: BlockWindows(); strcpy(DummyBuffer,LastConfig); DummyChar = PathPart(DummyBuffer); *DummyChar = 0; if(FileRequest = GetFile(Window,LocaleString(MSG_TERMMAIN_OPEN_PREFERENCES_TXT),DummyBuffer,FilePart(LastConfig),DummyBuffer,"#?.prefs",FALSE,FALSE,FALSE,NULL,TRUE)) { if(ReadConfig(DummyBuffer,PrivateConfig)) { SwapConfig(PrivateConfig,Config); strcpy(DummyBuffer,LastConfig); ConfigSetup(); ConfigChanged = FALSE; } else MyEasyRequest(Window,LocaleString(MSG_GLOBAL_ERROR_OPENING_FILE_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),DummyBuffer); FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Save the terminal preferences. */ case MEN_SAVE_SETTINGS: if(LastConfig[0]) { BlockWindows(); if(!WriteConfig(LastConfig,Config)) ShowError(Window,ERR_SAVE_ERROR,IoErr(),LastConfig); else ConfigChanged = FALSE; ReleaseWindows(); break; } /* Save the terminal preferences to a * given file name. */ case MEN_SAVE_SETTINGS_AS: BlockWindows(); strcpy(DummyBuffer,LastConfig); DummyChar = PathPart(DummyBuffer); *DummyChar = 0; if(FileRequest = GetFile(Window,LocaleString(MSG_TERMMAIN_SAVE_PREFERENCES_AS_TXT),DummyBuffer,FilePart(LastConfig),DummyBuffer,"#?.prefs",TRUE,FALSE,FALSE,NULL,TRUE)) { if(WriteConfig(DummyBuffer,Config)) { strcpy(LastConfig,DummyBuffer); ConfigChanged = FALSE; } else ShowError(Window,ERR_SAVE_ERROR,IoErr(),DummyBuffer); FreeAslRequest(FileRequest); } ReleaseWindows(); break; /* Show terminal information window. */ case MEN_STATUS_WINDOW: if(InfoWindow) CloseInfoWindow(); else OpenInfoWindow(); break; case MEN_REVIEW_WINDOW: if(ReviewWindow) DeleteReview(); else CreateReview(); break; /* Open the packet window if necessary, else * just activate it. */ case MEN_PACKET_WINDOW: CreatePacketWindow(); break; /* Toggle the presence of the fast! macro panel. */ case MEN_FAST_MACROS_WINDOW: if(FastWindow) CloseFastWindow(); else OpenFastWindow(); break; /* Open the upload queue window. */ case MEN_UPLOAD_QUEUE_WINDOW: CreateQueueProcess(); break; default:if(Code >= DIAL_MENU_LIMIT) { LONG Index = Code - DIAL_MENU_LIMIT; if(!LocalDialList && !Online) { if(LocalDialList = (struct List *)AllocVecPooled(sizeof(struct List),MEMF_ANY)) { LONG i; /* Clear previous list contents, we * don't want to redial yet. */ for(i = 0 ; i < NumPhoneEntries ; i++) Phonebook[i] -> Count = -1; NewList(LocalDialList); } } if(Phonebook[Index] -> Count == -1) { if(LocalDialList) { struct PhoneNode *NewNode; /* Create a new node to be added to the dial list. */ if(NewNode = (struct PhoneNode *)AllocVecPooled(sizeof(struct PhoneNode),MEMF_ANY | MEMF_CLEAR)) { /* Take care of the name and the corresponding phone book entry. */ NewNode -> VanillaNode . ln_Name = NewNode -> LocalName; NewNode -> Entry = Phonebook[Index]; Phonebook[Index] -> Count = ++LocalCount; SPrintf(NewNode -> LocalName,"%3ld - %s",LocalCount + 1,Phonebook[Index] -> Header -> Name); /* Install back-link. */ NewNode -> Entry -> Node = NewNode; AddTail(LocalDialList,&NewNode -> VanillaNode); } } } } break; } } /* HandleMenu(ULONG Code,ULONG Qualifier): * * Skip along the number of selected menu items and * handle the associated functions. */ VOID __regargs HandleMenu(ULONG Code,ULONG Qualifier) { struct MenuItem *MenuItem; DisplayReopened = FALSE; /* Check until the last menuitem has been * processed. */ while(Code != MENUNULL) { /* Pick up the associated menu item. */ if(MenuItem = ItemAddress(Menu,Code)) { HandleMenuCode((ULONG)GTMENUITEM_USERDATA(MenuItem),Qualifier); if(Apocalypse) return; if(DisplayReopened) { DisplayReopened = FALSE; return; } Code = MenuItem -> NextSelect; } else break; } HandleLocalDialList(FALSE); } /* HandleWorkbenchWindow(): * * Handle input coming from the Workbench window. */ BYTE HandleWorkbenchWindow() { struct FileInfoBlock *FileInfo; struct AppMessage *AppMessage; if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE)) { struct FileTransferInfo *Info; if(Info = AllocFileTransferInfo()) { LONG FilesFound = 0,i; BYTE Success = TRUE; while(AppMessage = (struct AppMessage *)GetMsg(WorkbenchPort)) { if(Success && AppMessage -> am_Type == MTYPE_APPWINDOW) { for(i = 0 ; Success && i < AppMessage -> am_NumArgs ; i++) { if(AppMessage -> am_ArgList[i] . wa_Lock && AppMessage -> am_ArgList[i] . wa_Name) { BPTR OldLock; if(OldLock = CurrentDir(AppMessage -> am_ArgList[i] . wa_Lock)) { BPTR FileLock; if(FileLock = Lock(AppMessage -> am_ArgList[i] . wa_Name,ACCESS_READ)) { if(Examine(FileLock,FileInfo)) { if(FileInfo -> fib_DirEntryType < 0) { if(NameFromLock(FileLock,SharedBuffer,512)) { if(!AddFileTransferNode(Info,SharedBuffer,FileInfo -> fib_Size)) Success = FALSE; else { FilesFound++; if(Config -> MiscConfig -> TransferIcons) { BPTR InfoLock; strcat(SharedBuffer,".info"); if(InfoLock = Lock(SharedBuffer,ACCESS_READ)) { if(Examine(InfoLock,FileInfo)) { if(FileInfo -> fib_DirEntryType < 0) { if(!AddFileTransferNode(Info,SharedBuffer,FileInfo -> fib_Size)) Success = FALSE; else FilesFound++; } } UnLock(InfoLock); } } } } } } UnLock(FileLock); } CurrentDir(OldLock); } } } } ReplyMsg((struct Message *)AppMessage); } if(FilesFound) { SortFileTransferInfo(Info); BlockWindows(); switch(MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_TRANSFER_FILES_AS_TXT),LocaleString(MSG_TERMMAIN_BINARY_UPLOAD_CANCEL_TXT))) { case 1: BinaryTransfer = TRUE; FileTransferInfo = Info; StartXprSendFromList(TRANSFER_BINARY,TRUE); break; case 2: BinaryTransfer = FALSE; FileTransferInfo = Info; StartXprSendFromList(TRANSFER_TEXT,TRUE); break; case 0: FreeFileTransferInfo(Info); break; } ReleaseWindows(); } } FreeDosObject(DOS_FIB,FileInfo); } while(AppMessage = (struct AppMessage *)GetMsg(WorkbenchPort)) ReplyMsg((struct Message *)AppMessage); return(FALSE); } /* HandleIconify(): * * Handle program iconification. */ VOID HandleIconify() { BYTE Released = FALSE; /* Set the wait mouse pointer... */ BlockWindows(); /* Open workbench.library. */ if(WorkbenchBase) { /* Open icon.library. */ if(IconBase) { struct DiskObject *Icon; if(!(Icon = GetProgramIcon())) Icon = GetDefDiskObject(WBTOOL); /* Did we get an icon? */ if(Icon) { struct MsgPort *IconPort; /* Reset the icon type. */ Icon -> do_Type = NULL; /* Default icon position. */ Icon -> do_CurrentX = NO_ICON_POSITION; Icon -> do_CurrentY = NO_ICON_POSITION; /* Create the Workbench reply port. */ if(IconPort = CreateMsgPort()) { struct AppIcon *AppIcon; /* Add the application icon. */ if(AppIcon = AddAppIcon(0,0,TermIDString,IconPort,NULL,Icon,TAG_DONE)) { struct AppMessage *AppMessage; UBYTE *String,*Error; ULONG SignalSet; /* Reset the guardian. */ IconTerminated = FALSE; /* Release the window. */ Released = TRUE; ReleaseWindows(); WindowBox . Left = Window -> LeftEdge; WindowBox . Top = Window -> TopEdge; WindowBox . Width = Window -> Width; WindowBox . Height = Window -> Height; /* Close the display. full stop. */ if(DeleteDisplay()) { /* Reset and release the serial driver. */ if(Config -> MiscConfig -> ReleaseDevice) { ClearSerial(); DeleteSerial(); } /* Wait for double-click. */ IconLoop: while(!IconTerminated) { SignalSet = Wait(PORTMASK(IconPort) | SIG_REXX | SIGBREAKF_CTRL_F); if(SignalSet & PORTMASK(IconPort)) { /* Pick up application messages. */ while(AppMessage = (struct AppMessage *)GetMsg(IconPort)) { /* Received a double-click? */ IconTerminated = TRUE; ReplyMsg(AppMessage); } } /* Wake up if ARexx command received. */ if(SignalSet & SIG_REXX) while(HandleRexx()); if(SignalSet & SIGBREAKF_CTRL_F) IconTerminated = TRUE; } /* Open the serial driver. */ if(Config -> MiscConfig -> ReleaseDevice) { if(Error = CreateSerial()) { DeleteSerial(); switch(MyEasyRequest(NULL,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_TERMMAIN_ICONIFY_IGNORE_QUIT_TXT),Error)) { case 1: IconTerminated = FALSE; goto IconLoop; case 0: MainTerminated = TRUE; } } else { if(SerialMessage) { MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SerialMessage); SerialMessage = NULL; } } } if(CantQuit && MainTerminated) MainTerminated = FALSE; /* Create the display. */ if(!MainTerminated) { if(String = CreateDisplay(FALSE)) { if(MyEasyRequest(NULL,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_TERMMAIN_ICONIFY_QUIT_TXT),String)) { ClearSerial(); DeleteSerial(); IconTerminated = FALSE; goto IconLoop; } else MainTerminated = FALSE; } else { BumpWindow(Window); PubScreenStuff(); } } } else { BlockWindows(); MyEasyRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),LocaleString(MSG_TERMMAIN_CANNOT_CLOSE_SCREEN_YET_TXT)); ReleaseWindows(); } /* Remove the application icon. */ RemoveAppIcon(AppIcon); /* Reply pending messages. */ while(AppMessage = (struct AppMessage *)GetMsg(IconPort)) ReplyMsg(AppMessage); } else MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_ADD_APPLICATION_ICON_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); DeleteMsgPort(IconPort); } else MyEasyRequest(Window,LocaleString(MSG_GLOBAL_FAILED_TO_CREATE_MSGPORT_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); FreeDiskObject(Icon); } else MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_OPEN_TOOL_ICON_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); } else MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_OPEN_ICON_LIBRARY_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); } else MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_OPEN_WORKBENCH_LIBRARY_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT)); if(!Released) ReleaseWindows(); /* Finished! */ DoIconify = FALSE; } /* HandleOnlineCleanup(): * * Perform offline cleanup tasks. */ VOID HandleOnlineCleanup() { SoundPlay(SOUND_DISCONNECT); StopCall(FALSE); if(CurrentPay) { /* Reset the text rendering styles, font, etc. in * order to keep the following text from getting * illegible. */ SoftReset(); /* Display how much we expect * the user will have to pay for * this call. */ ConWrites(LocaleString(MSG_TERMMAIN_THIS_CALL_WILL_COST_YOU_TXT),CreateSum(CurrentPay,TRUE)); LogAction(LocaleString(MSG_TERMAUX_CARRIER_LOST_COST_TXT),CreateSum(CurrentPay,TRUE)); CurrentPay = 0; } else LogAction(LocaleString(MSG_TERMAUX_CARRIER_LOST_TXT)); SetDialMenu(TRUE); /* Execute logoff macro. */ if(Config -> CommandConfig -> LogoffMacro[0]) SerialCommand(Config -> CommandConfig -> LogoffMacro); /* Clear the password. */ Password[0] = 0; UserName[0] = 0; CurrentBBSName[0] = 0; CurrentBBSComment[0] = 0; CurrentBBSNumber[0] = 0; WasOnline = FALSE; ChosenEntry = NULL; LimitCount = -1; /* Previous configuration available? */ if(BackupConfig) { /* Remember old configuration. */ SaveConfig(Config,PrivateConfig); /* Copy configuration. */ SaveConfig(BackupConfig,Config); /* Set up new configuration. */ ConfigSetup(); /* Free old configuration. */ DeleteConfiguration(BackupConfig); BackupConfig = NULL; } if(Config -> ModemConfig -> RedialAfterHangup) { if(DialList) { if(DialList -> lh_Head -> ln_Succ) DoDial = DIAL_REDIAL; } } } /* HandleFlowChange(): * * Handle data flow scanner information. */ VOID HandleFlowChange() { if(!Online && (FlowInfo . Voice || FlowInfo . Ring || FlowInfo . Connect)) { if(FlowInfo . Voice) { UBYTE DateTimeBuffer[256]; FormatStamp(NULL,NULL,NULL,DateTimeBuffer,FALSE); WakeUp(Window,SOUND_VOICE); ConWrites(LocaleString(MSG_TERMMAIN_INCOMING_VOIC_CALL_TXT),DateTimeBuffer); Say(LocaleString(MSG_TERMMAIN_SAY_INCOMING_VOICE_CALL_TXT)); } if(FlowInfo . Ring) { UBYTE DateTimeBuffer[256]; FormatStamp(NULL,NULL,NULL,DateTimeBuffer,FALSE); WakeUp(Window,SOUND_RING); ConWrites(LocaleString(MSG_TERMMAIN_INCOMING_CALL_TXT),DateTimeBuffer); Say(LocaleString(MSG_GLOBAL_INCOMING_CALL_TXT)); } if(FlowInfo . Connect) { WakeUp(Window,SOUND_CONNECT); Online = TRUE; BaudPending = FALSE; SetDialMenu(FALSE); } } /* Check if we are to prompt the user for * ZModem upload type. */ if(UsesZModem && FlowInfo . ZModemUpload && XProtocolBase) { if(Config -> MiscConfig -> AutoUpload) { BlockWindows(); switch(UploadPanel()) { case UPLOAD_TEXT: BinaryTransfer = FALSE; if(!StartXprSend(TRANSFER_TEXT,TRUE)) SerWrite(ZModemCancel,20); break; case UPLOAD_BINARY: BinaryTransfer = TRUE; if(!StartXprSend(TRANSFER_BINARY,TRUE)) SerWrite(ZModemCancel,20); break; case UPLOAD_ABORT: SerWrite(ZModemCancel,20); break; case UPLOAD_BINARY_FROM_LIST: StartUpload(UPLOAD_BINARY); break; case UPLOAD_TEXT_FROM_LIST: StartUpload(UPLOAD_TEXT); break; } ReleaseWindows(); } } FlowInit(TRUE); } /* HandleSerialReset(): * * Handle serial device reset. */ VOID HandleSerialReset() { ClearSerial(); DeleteSerial(); BlockWindows(); ReopenSerial(); ReleaseWindows(); } /* HandleSerialRelease(): * * Release the serial device driver, then reopen it again. */ VOID HandleSerialRelease() { APTR OldPtr = ThisProcess -> pr_WindowPtr; BYTE Continue,SerialClosed; ThisProcess -> pr_WindowPtr = (APTR)Window; /* This might happen if an ARexx user * released the serial device and * failed to reopen it. */ if(ReadPort) SerialClosed = FALSE; else SerialClosed = TRUE; BlockWindows(); /* Prevent catastrophes! */ if(Online && !SerialClosed) { if(!MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_YOU_ARE_STILL_ONLINE_TXT),LocaleString(MSG_GLOBAL_YES_NO_TXT))) Continue = FALSE; else Continue = TRUE; } else Continue = TRUE; if(Continue) { if(SerialClosed) ReopenSerial(); else { ClearSerial(); DeleteSerial(); if(MyEasyRequest(Window,LocaleString(MSG_TERMMAIN_UNIT_RESET_AND_RELEASED_TXT),LocaleString(MSG_TERMMAIN_RETURN_QUIT_TXT),Config -> SerialConfig -> SerialDevice,Config -> SerialConfig -> UnitNumber)) ReopenSerial(); else MainTerminated = TRUE; } } ReleaseSerial = FALSE; ThisProcess -> pr_WindowPtr = OldPtr; ReleaseWindows(); } /* HandleExternalEmulation(): * * Handle external emulation event. */ VOID HandleExternalEmulation() { if(!XEmulatorSignal(XEM_IO,XEM_Signal)) { CloseEmulator(); ResetDisplay = TRUE; } } /* HandleSerialCheck(): * * Handle routine checkup actions. */ BYTE HandleSerialCheck() { /* Take a look at the carrier signal. */ if(Online && Config -> SerialConfig -> CheckCarrier && ReadPort && Status == STATUS_READY) { /* Query serial status. */ WriteRequest -> IOSer . io_Command = SDCMD_QUERY; DoIO(WriteRequest); /* Is the carrier detect signal * still present? */ if(WriteRequest -> io_Status & CIAF_COMCD) { WasOnline = TRUE; Online = FALSE; } } /* Check online time limit. */ if(!LimitCount) { LimitCount = -1; BlockWindows(); SendARexxCommand(LimitMacro); ReleaseWindows(); } /* Flush capture file contents to disk, * this routine is executed each minute * in order to store the captured data. */ if(!BufferFlushCount--) { BufferFlushCount = 60; /* Flush the capture file. */ if(FileCapture) BufferFlush(FileCapture); } return(FALSE); } /* HandleQueueMsg(): * * Process the special message queue. */ BYTE HandleQueueMsg() { struct DataMsg *Item; if(Item = GetMsgItem(SpecialQueue)) { struct FileTransferInfo *Info; BYTE OldEcho; switch(Item -> Type) { // Output data. case DATAMSGTYPE_WRITE: SerWrite(Item -> Data,Item -> Size); break; // Execute a command. case DATAMSGTYPE_SERIALCOMMAND: SerialCommand(Item -> Data); break; // Execute a command, but don't echo it. case DATAMSGTYPE_SERIALCOMMANDNOECHO: OldEcho = Config -> SerialConfig -> Duplex; Config -> SerialConfig -> Duplex = DUPLEX_FULL; SerialCommand(Item -> Data); Config -> SerialConfig -> Duplex = OldEcho; break; // Output contents of clipboard case DATAMSGTYPE_WRITECLIP: if(!ClipInput) { if(!OpenClip(Item -> Size)) ClipInput = ClipXerox = TRUE; else ClipInput = ClipXerox = FALSE; } /* Are we reading input from the clipboard? */ if(ClipInput) { UBYTE InputBuffer[257]; WORD Len; if((Len = GetClip(InputBuffer,256,FALSE)) < 0) { CloseClip(); ClipInput = FALSE; if(ClipXerox) { if(Config -> ClipConfig -> InsertSuffix[0]) SerialCommand(Config -> ClipConfig -> InsertSuffix); ClipXerox = FALSE; } ClipPrefix = FALSE; } else { if(!ClipPrefix && ClipXerox) { if(Config -> ClipConfig -> InsertPrefix[0]) SerialCommand(Config -> ClipConfig -> InsertPrefix); ClipPrefix = TRUE; } if(Len > 0) SendInputTextBuffer(InputBuffer,Len,FALSE); } } break; // Start an upload case DATAMSGTYPE_UPLOAD: if(Info = AllocFileTransferInfo()) { struct FileInfoBlock *FileInfo; LONG FilesFound = 0,Type = Item -> Size; if(FileInfo = (struct FileInfoBlock *)AllocDosObject(DOS_FIB,TAG_DONE)) { BPTR FileLock; struct List *List; struct Node *Node,*Next; APTR OldPtr = ThisProcess -> pr_WindowPtr; ThisProcess -> pr_WindowPtr = (APTR)-1; List = (struct List *)Item -> Data; for(Node = List -> lh_Head ; Next = Node -> ln_Succ ; Node = Next) { if(FileLock = Lock(Node -> ln_Name,ACCESS_READ)) { if(Examine(FileLock,FileInfo)) { if(FileInfo -> fib_DirEntryType < 0) { if(AddFileTransferNode(Info,Node -> ln_Name,FileInfo -> fib_Size)) FilesFound++; if(Config -> MiscConfig -> TransferIcons) { BPTR InfoLock; strcpy(SharedBuffer,Node -> ln_Name); strcat(SharedBuffer,".info"); if(InfoLock = Lock(SharedBuffer,ACCESS_READ)) { if(Examine(InfoLock,FileInfo)) { if(FileInfo -> fib_DirEntryType < 0) { if(AddFileTransferNode(Info,SharedBuffer,FileInfo -> fib_Size)) FilesFound++; } } UnLock(InfoLock); } } Remove(Node); FreeVecPooled(Node); } } UnLock(FileLock); } } ThisProcess -> pr_WindowPtr = OldPtr; FreeDosObject(DOS_FIB,FileInfo); } DeleteMsgItem(Item); Item = NULL; if(FilesFound) { BlockWindows(); SortFileTransferInfo(Info); switch(Type) { case UPLOAD_BINARY: BinaryTransfer = TRUE; FileTransferInfo = Info; StartXprSendFromList(TRANSFER_BINARY,TRUE); break; case UPLOAD_TEXT: BinaryTransfer = FALSE; FileTransferInfo = Info; StartXprSendFromList(TRANSFER_TEXT,TRUE); break; } ReleaseWindows(); } else FreeFileTransferInfo(Info); } break; // ARexx script execution finished. case DATAMSGTYPE_COMMANDDONE: if(CantQuit > 0) CantQuit--; BumpWindow(Window); ReleaseWindows(); break; // Call a menu item case DATAMSGTYPE_MENU: HandleMenuCode((ULONG)Item -> Size,(ULONG)Item -> Data); break; // Rendezvous with external process case DATAMSGTYPE_RENDEZVOUS: if(ReadRequest && WriteRequest) { // Abort serial I/O processing ClearSerial(); BlockWindows(); // Return the message, caution, we're not ready yet Forbid(); DeleteMsgItem(Item); Item = NULL; // Prepare to wait... ClrSignal(SIG_HANDSHAKE); Wait(SIG_HANDSHAKE); // Pick up the queue RestartSerial(FALSE); Permit(); ReleaseWindows(); } break; } if(Item) DeleteMsgItem(Item); return(TRUE); } else return(FALSE); } /* HandleOwnDevUnit(): * * Deal with the OwnDevUnit signal notification. */ BYTE HandleOwnDevUnit() { if(!Online || !ReadPort) HandleSerialRelease(); return(FALSE); }